package com.clip.service;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.clip.dao.ClipEventDao;
import com.clip.dao.ClipmessageDAO;
import com.clip.dao.ContactDAO;
import com.clip.dao.MsgNoticeDAO;
import com.clip.dao.SharemappingDAO;
import com.clip.dao.SystemMessageDAO;
import com.clip.dao.UserDAO;
import com.clip.dao.UserEmailEventDAO;
import com.clip.entity.ClipEvent;
import com.clip.entity.Clipmessage;
import com.clip.entity.MsgNotice;
import com.clip.entity.Sharemapping;
import com.clip.entity.SystemMessage;
import com.clip.entity.User;
import com.clip.entity.UserEmail;
import com.clip.entity.UserEmailEvent;
import com.clip.util.ToolsUtils;

@Service
@Transactional
public class MessageService {
	
	@Autowired
	private UserEmailEventDAO userEmailEventDAO;
	@Autowired
	private ClipEventDao clipEventDao;
	@Autowired
	private UserDAO userDAO;
	@Autowired
	private MsgNoticeDAO msgNoticeDAO;
	@Autowired
	private ContactDAO contactDAO;
	@Autowired
	private ClipmessageDAO clipmessageDAO; 
	@Autowired
	private SharemappingDAO	sharemappingDAO;
	@Autowired
	private SystemMessageDAO systemMessageDAO;
	
	private String getBindEmail(User user){
		String hql_email = "SELECT ue FROM UserEmail ue WHERE ue.uid="+user.getId()+" AND ue.bindable=1 GROUP BY ue.email";
		List<UserEmail> ueList = this.userEmailEventDAO.findByQuery(hql_email);
		String str = "";
		for(int i=0;i<ueList.size();i++){
			str += i==0 ? ("'"+ueList.get(i).getEmail()+"'") : (",'"+ueList.get(i).getEmail()+"'");
		}
		str = str.length()>0 ? str : "''"; 
		return str;
	}
	/**
	 * @param user
	 * @return 	request		->User
	 *			systemmsg	->SystemMessage
	 *			comment		->Clipmessage
	 *			remind		->ClipEvent
	 * 			
	 */
	public Map<String,Object> findMessageCount(User user){
//		Calendar startCalendar = Calendar.getInstance();
//		Calendar endCalendar = Calendar.getInstance();
//		startCalendar.clear(Calendar.MILLISECOND);
//		startCalendar.clear(Calendar.SECOND);
//		startCalendar.clear(Calendar.MINUTE);
//		startCalendar.set(Calendar.HOUR_OF_DAY, 0);
//		endCalendar.clear(Calendar.MILLISECOND);
//		endCalendar.clear(Calendar.SECOND);
//		endCalendar.clear(Calendar.MINUTE);
//		endCalendar.set(Calendar.HOUR_OF_DAY, 0);
//		endCalendar.add(Calendar.DAY_OF_MONTH, 1);
		Calendar now=Calendar.getInstance();
		
		String hql_remind = "SELECT COUNT(*) FROM ClipEvent ce WHERE ce.uid="+user.getId()+" AND ce.alerttime>0 AND ce.alerttime <="+now.getTimeInMillis();
		String hql_request = "SELECT COUNT(*) FROM UserEmailEvent uel WHERE uel.obj IN ("+getBindEmail(user)+") AND uel.type=3 AND uel.status=0";
		String query_newinvite="SELECT COUNT(*) FROM SystemMessage msg WHERE msg.checkstatus=0 and msg.uid="+user.getId();
		String query_newcomment="SELECT COUNT(*) FROM MsgNotice notice WHERE notice.checkstatus=0 AND notice.uid="+user.getId();
		
		
		
		Map<String,Object> map = new LinkedHashMap<String,Object>();
		map.put("remind", this.userEmailEventDAO.findByQueryWithUniqueResult(hql_remind));
		if(user.getUsertype()==1)
			map.put("request", this.userEmailEventDAO.findByQueryWithUniqueResult(hql_request));
		map.put("systemmsg", this.userEmailEventDAO.findByQueryWithUniqueResult(query_newinvite));
		map.put("comment", this.userEmailEventDAO.findByQueryWithUniqueResult(query_newcomment));
		return map;
	}
	/**
	 * @param type : request,systemmsg,comment,remind
	 * @param currentUser
	 * @return 返回对象 list request		->User
	 * 						systemmsg	->SystemMessage
	 * 						comment		->Clipmessage
	 * 						remind		->ClipEvent
	 * 			
	 */
	public List findMessage(String type,User currentUser){
		Map<String,Object> map = new LinkedHashMap<String,Object>();
		
		Calendar now = Calendar.getInstance();
		String hql_request = "SELECT uel FROM UserEmailEvent uel WHERE uel.obj IN ("+getBindEmail(currentUser)+") AND uel.type=3 AND uel.status=0 GROUP BY uel.id ORDER BY uel.actDate DESC";
		List list=new ArrayList();
		if(type.equals("request")){
			List<UserEmailEvent> ueList = userEmailEventDAO.findByQuery(hql_request);
			for(UserEmailEvent ue : ueList){
				User user = userDAO.findById(ue.getUid());
				if(user!=null)
					list.add(user);
				else
					this.userEmailEventDAO.delete(ue);
			}
		}else if(type.equals("systemmsg")){
			List<SystemMessage> systemmsglist=this.systemMessageDAO.findByQuery("from SystemMessage msg where msg.uid=? order by msg.msgtime desc", new Object[]{currentUser.getId()});
			list=systemmsglist;
		}else if(type.equals("comment")){
			List<MsgNotice> noticelist=this.msgNoticeDAO.findByQuery("from MsgNotice notice where notice.uid=? order by notice.msgtime desc", new Object[]{currentUser.getId()});
			list=noticelist;
		}else if(type.equals("remind")){
			List<ClipEvent> celist=this.clipEventDao.findByQuery("FROM ClipEvent ce WHERE ce.uid="+currentUser.getId()+" AND ce.alerttime>0 AND ce.alerttime<="+now.getTimeInMillis()+" ORDER BY ce.alerttime desc");
			list=celist;
		}
		return list;
	}
	private Map<String,Object> getMsgNoticeMap(MsgNotice notice,int currentuid) {
		Map<String,Object> infoMap = new HashMap<String,Object>();
		ClipEvent clipEvent=this.clipEventDao.findById(notice.getEventid());
		int commentuid=notice.getUid();
		List temp=this.contactDAO.findByQuery("select c.name from Contact c where c.uid="+currentuid+" and c.contactuid="+commentuid);
		if(temp!=null&&temp.size()>0){
			infoMap.put("commentusername", temp.get(0));
		}else{
			User user=this.userDAO.findById(commentuid);
			infoMap.put("commentusername", user.getName());
		}
		Clipmessage clipmessage=this.clipmessageDAO.findById(notice.getMsgid());
		infoMap.put("replycontent", ToolsUtils.xmlCDATA(clipmessage.getContent()));
		infoMap.put("eventid", clipEvent.getId());
		infoMap.put("title", ToolsUtils.xmlCDATA(clipEvent.getTitle()));
		infoMap.put("type", 3);
		return infoMap;
	}
	private Map<String,Object> getClipEventMap(ClipEvent ce){
		Map<String,Object> infoMap = new LinkedHashMap<String,Object>();
		infoMap.put("code", ce.getId());
		infoMap.put("title", "<![CDATA[<b>档期提醒</b>]]>");
		infoMap.put("context", "<![CDATA[内容："+ce.getTitle()+"]]>");
		infoMap.put("type", 1);
		return infoMap;
	}
	private Map<String,Object> getUserEmailEventMap(UserEmailEvent ue){
		User user = userDAO.findById(ue.getUid());
		Map<String,Object> infoMap = new LinkedHashMap<String,Object>();
		infoMap.put("code", ue.getCode());
		infoMap.put("title", "<![CDATA[<b><i>"+user.getName()+"</i>想加您为好友</b>]]>");
		if(ue.getObj1()!=null)
			infoMap.put("context", "<![CDATA["+ue.getObj1()+"]]>");
		else
			infoMap.put("context", "");
		infoMap.put("type", 2);
		return infoMap;
	}
	public void ignoreMessage(int noticeid) {
		MsgNotice msgNotice=this.msgNoticeDAO.findById(noticeid);
		msgNotice.setCheckstatus(1);
		this.msgNoticeDAO.attachDirty(msgNotice);
	}
	public boolean ignoreMessage(int uid,int noticeid) {
		MsgNotice msgNotice=this.msgNoticeDAO.findById(noticeid);
		if(msgNotice.getUid()==uid){
			msgNotice.setCheckstatus(1);
			this.msgNoticeDAO.attachDirty(msgNotice);
			return true;
		}else{
			return false;
		}
	}
	public List getContactRequests(User currentUser) {
		List list=new ArrayList();
		String hql_request = "SELECT uel FROM UserEmailEvent uel WHERE uel.obj IN ("+getBindEmail(currentUser)+") AND uel.type=3 AND uel.status=0 ORDER BY uel.actDate DESC";
		List<UserEmailEvent> ueList = userEmailEventDAO.findByQuery(hql_request);
		for(UserEmailEvent ue : ueList){
			User user = userDAO.findById(ue.getUid());
			list.add(user);
		}
		return list;
	}
	public long countNewComment(User currentUser) {
		String hql_newcomment="SELECT notice from MsgNotice notice where notice.uid="+currentUser.getId()+" and exists ( from ClipEvent ce where notice.eventid=ce.id )";
		return this.msgNoticeDAO.countByQuery(hql_newcomment);
	}
	public List getNewComment(User currentUser,int needpagenum,int pagelength) {
		String hql_newcomment="SELECT notice from MsgNotice notice where notice.uid=? and exists ( from ClipEvent ce where notice.eventid=ce.id ) order by notice.msgtime desc";
		List list=this.msgNoticeDAO.pagingByQuery(hql_newcomment,needpagenum,pagelength,new Object[]{currentUser.getId()});
		for (Object object : list) {
			MsgNotice msgNotice=(MsgNotice) object;
			if(msgNotice.getCheckstatus()==0){
				msgNotice.setCheckstatus(1);
				this.msgNoticeDAO.attachDirty(msgNotice);
			}
		}
		return list;
	}
	public Clipmessage findBymessageid(int messageid){
		return this.clipmessageDAO.findById(messageid);
	}
	
	/**
	 * @param uid
	 * @return 	0	通知 SystemMessage
	 * 			1	评论 MsgNotice
	 * 			2	提醒 ClipEvent->alerttime
	 */
	public List checkmsg(Calendar now,int uid) {
		Calendar startCalendar = (Calendar) now.clone();
		Calendar endCalendar = (Calendar) now.clone();
		startCalendar.clear(Calendar.MILLISECOND);
		startCalendar.clear(Calendar.SECOND);
		startCalendar.clear(Calendar.MINUTE);
		startCalendar.set(Calendar.HOUR_OF_DAY, 0);
		endCalendar.clear(Calendar.MILLISECOND);
		endCalendar.clear(Calendar.SECOND);
		endCalendar.clear(Calendar.MINUTE);
		endCalendar.set(Calendar.HOUR_OF_DAY, 0);
		endCalendar.add(Calendar.DAY_OF_MONTH, 1);
		
		List returnList=new ArrayList();
		String hql_remind = "SELECT count(*) FROM ClipEvent ce WHERE ce.uid="+uid+" AND ce.alerttime>0 AND ce.alerttime<="+now.getTimeInMillis();
		int remindcount=clipEventDao.countByQuery(hql_remind);
		String hql_newinvite="SELECT COUNT(*) from SystemMessage msg where msg.checkstatus=0 and msg.uid="+uid;
		int newinvitecount=clipEventDao.countByQuery(hql_newinvite);
		String hql_newcomment="SELECT count(*) from MsgNotice notice where notice.checkstatus=0 and notice.uid="+uid+" and exists ( from ClipEvent ce where notice.eventid=ce.id )";
		int newcommentcount=(Integer)msgNoticeDAO.countByQuery(hql_newcomment);
		returnList.add(newinvitecount);
		returnList.add(newcommentcount);
		returnList.add(remindcount);
		return returnList;
	}
	public boolean messageWithClipevent(int uid, int eventid, int acceptstatus) {
		boolean flag=false;
		List list=this.sharemappingDAO.findByQuery("from Sharemapping map where map.eventid="+eventid+" and map.share2uid="+uid);
		if(list!=null&&list.size()==1){
			Sharemapping sharemapping=(Sharemapping) list.get(0);
			sharemapping.setAcceptstatus(acceptstatus);
			this.sharemappingDAO.attachDirty(sharemapping);
			flag=true;
		}
		return flag;
	}
	
	public long countSystemMessage(int uid){
		String sql="from SystemMessage msg where msg.uid="+uid;
		return (Long) this.systemMessageDAO.countByQuery(sql);
	}
	
	public List getSystemMessage(int uid,int currentpage,int pagelength){
		String sql="from SystemMessage msg where msg.uid=? order by msg.msgtime desc";
		List list=this.systemMessageDAO.pagingByQuery(sql, currentpage, pagelength, new Object[]{uid});
		for (Object object : list) {
			SystemMessage systemMessage=(SystemMessage) object;
			if(systemMessage.getCheckstatus()==0){
				systemMessage.setCheckstatus(1);
				this.systemMessageDAO.attachDirty(systemMessage);
			}
		}
		return list;
	}
	public boolean deleteSystemMessage(int uid, int msgid) {
		boolean result=false;
		String sql="from SystemMessage msg where msg.uid=? and msg.id=?";
		List list=this.systemMessageDAO.findByQuery(sql,new Object[]{uid,msgid});
		if(list==null||list.size()==0)
			return result;
		else{
			SystemMessage message=(SystemMessage) list.get(0);
			if(message.getMsgtype()==SystemMessage.CANCELTYPE){
				int eventid=message.getEventid();
				ClipEvent clipEvent=this.clipEventDao.findById(eventid);
				String sqlDelEvent=null;
				if(clipEvent.getSeid()==0&&clipEvent.getEventtype()==2)
					sqlDelEvent="delete from ClipEvent ce where ce.uid="+uid+" and ce.seid="+clipEvent.getId();
				else
					sqlDelEvent="delete from ClipEvent ce where ce.uid="+uid+" and ce.reliedclip="+clipEvent.getId();
				this.clipEventDao.updateByQuery(sqlDelEvent);
				String sqlDelSharemapping="delete from Sharemapping map where map.eventid="+message.getEventid()+" and map.share2uid="+uid;
				this.sharemappingDAO.excuteUpdateQuery(sqlDelSharemapping);
			}
			this.systemMessageDAO.delete(message);
			result=true;
			return result;
		}
	}
	
	public void deleteSystemMessage(SystemMessage systemMessage) {
		this.systemMessageDAO.delete(systemMessage);
	}
	
	public void updateSystemMessage(SystemMessage systemMessage) {
		this.systemMessageDAO.attachDirty(systemMessage);
	}
	public void updateMsgNotice(MsgNotice msgNotice) {
		this.msgNoticeDAO.attachDirty(msgNotice);
	}
	public void deleteMsgNotice(MsgNotice msgNotice) {
		this.msgNoticeDAO.delete(msgNotice);
	}
	
	public boolean deleteMsgNotice(int uid, int noticeid) {
		MsgNotice msgNotice=this.msgNoticeDAO.findById(noticeid);
		if(msgNotice.getUid()!=uid)
			return false;
		else{
			this.msgNoticeDAO.delete(msgNotice);
			return true;
		}
	}
	public int findBymessageid(int uid, int eventid, int msgtype) {
		if(msgtype==SystemMessage.CANCELTYPE){
			String sql="from SystemMessage msg where msg.msgtype=? and msg.uid=? and msg.eventid=?";
			List list=this.systemMessageDAO.findByQuery(sql,new Object[]{SystemMessage.CANCELTYPE,uid,eventid});
			if(list!=null&&list.size()==1){
				SystemMessage msg=(SystemMessage) list.get(0);
				if(msg.getCheckstatus()==0){
					msg.setCheckstatus(1);
					this.systemMessageDAO.attachDirty(msg);
				}
				return msg.getId();
			}else{
				return 0;
			}
		}
		return 0;
	}
	public boolean deleteRecycleClipMessage(int uid, int eventid) {
		ClipEvent clipEvent=this.clipEventDao.findById(eventid);
		if(clipEvent==null){
			return false;
		}
		List systemmsgList=this.systemMessageDAO.findByQuery(
				"from SystemMessage sys where sys.uid=? and sys.eventid=? and sys.fromuid=? and sys.msgtype=1", 
				new Object[]{uid,eventid,clipEvent.getUid()});
		if(systemmsgList!=null&&systemmsgList.size()>0){
			SystemMessage message=(SystemMessage) systemmsgList.get(0);
			String sqlDelEvent=null;
			if(clipEvent.getSeid()==0&&clipEvent.getEventtype()==2)
				sqlDelEvent="delete from ClipEvent ce where ce.uid="+uid+" and ce.seid="+clipEvent.getId();
			else
				sqlDelEvent="delete from ClipEvent ce where ce.uid="+uid+" and ce.reliedclip="+clipEvent.getId();
			this.clipEventDao.updateByQuery(sqlDelEvent);
			String sqlDelSharemapping="delete from Sharemapping map where map.eventid="+message.getEventid()+" and map.share2uid="+uid;
			this.sharemappingDAO.excuteUpdateQuery(sqlDelSharemapping);
			this.systemMessageDAO.delete(message);
		}
		return true;
	}
}
